const express = require('express')
const router = express.Router()
const axios = require('axios')

// 微信公众号配置（优先读取环境变量）
const wxConfig = {
  appid: process.env.WX_APPID || 'wx7d893c7479026ad1',
  secret: process.env.WX_SECRET || '7147c6ac4474da45c9e978901fb1990a',
}

// 简单的 access_token 内存缓存，减少频繁获取
let tokenCache = { access_token: null, expires_at: 0 }

async function getAccessToken() {
  const now = Date.now()
  if (tokenCache.access_token && tokenCache.expires_at > now + 5000) {
    return { access_token: tokenCache.access_token }
  }

  const url = 'https://api.weixin.qq.com/cgi-bin/token'
  const { data } = await axios({
    method: 'get',
    url,
    params: {
      grant_type: 'client_credential',
      appid: wxConfig.appid,
      secret: wxConfig.secret,
    },
  })

  if (data?.errcode) {
    // 例如 40013 AppID 无效
    throw new Error(JSON.stringify(data))
  }

  // 正常返回：{"access_token":"ACCESS_TOKEN","expires_in":7200}
  tokenCache.access_token = data.access_token
  tokenCache.expires_at = now + (data.expires_in || 7200) * 1000
  return data
}

// GET /api/weixin/token - 用于调试验证 access_token 获取
router.get('/token', async (req, res) => {
  try {
    const tokenInfo = await getAccessToken()
    res.json(tokenInfo)
  } catch (err) {
    res.status(400).json({ message: err.message || '获取 access_token 失败' })
  }
})

// GET /api/weixin/templates - 拉取当前公众号私有模板列表
router.get('/templates', async (req, res) => {
  try {
    const tokenInfo = await getAccessToken()
    const url = 'https://api.weixin.qq.com/cgi-bin/template/get_all_private_template'
    const { data } = await axios({ method: 'get', url, params: { access_token: tokenInfo.access_token } })
    if (data?.errcode && data.errcode !== 0) {
      return res.status(400).json(data)
    }
    return res.json(data)
  } catch (err) {
    const message = err?.response?.data || { message: err.message || '获取模板列表失败' }
    return res.status(400).json(message)
  }
})

// POST /api/weixin/sendTemplateMessage - 发送公众号模板消息
router.post('/sendTemplateMessage', async (req, res) => {
  try {
    const { touser, template_id, data: tmplData, url, miniprogram, client_msg_id } = req.body || {}
    const missing = []
    if (!touser) missing.push('接收者 OpenID')
    if (!template_id) missing.push('模板 ID')
    const isDataEmpty = !tmplData || (typeof tmplData === 'object' && Object.keys(tmplData).length === 0)
    if (isDataEmpty) missing.push('模板数据')
    if (missing.length) {
      return res.status(400).json({ message: '必填参数不能为空：' + missing.join('、') })
    }

    const tokenInfo = await getAccessToken()

    const sendUrl = 'https://api.weixin.qq.com/cgi-bin/message/template/send'
    const payload = {
      touser,
      template_id,
      url,
      miniprogram,
      client_msg_id,
      data: tmplData,
    }

    const { data } = await axios({
      method: 'post',
      url: sendUrl,
      params: { access_token: tokenInfo.access_token },
      data: payload,
    })

    if (data?.errcode && data.errcode !== 0) {
      return res.status(400).json(data)
    }
    return res.json(data)
  } catch (err) {
    const message = err?.response?.data || { message: err.message || '发送模板消息失败' }
    return res.status(400).json(message)
  }
})

// 获取所有关注者 OpenID（分页）
async function getAllOpenIds(access_token) {
  const url = 'https://api.weixin.qq.com/cgi-bin/user/get'
  let next = ''
  const list = []
  while (true) {
    const { data } = await axios.get(url, {
      params: { access_token, next_openid: next },
    })
    if (data?.errcode && data.errcode !== 0) {
      throw new Error(JSON.stringify(data))
    }
    const arr = data?.data?.openid || []
    list.push(...arr)
    next = data?.next_openid || ''
    if (!next || arr.length === 0) break
  }
  return list
}

// 按批次并发发送模板消息（简单限流）
async function sendTemplateToMany(access_token, template_id, basePayload, openids, batch = 5, delayMs = 200) {
  const sendUrl = 'https://api.weixin.qq.com/cgi-bin/message/template/send'
  let success = 0
  let failure = 0
  const errors = []

  for (let i = 0; i < openids.length; i += batch) {
    const slice = openids.slice(i, i + batch)
    await Promise.all(
      slice.map(async (openid) => {
        const payload = { ...basePayload, touser: openid, template_id }
        try {
          const { data } = await axios.post(sendUrl, payload, { params: { access_token } })
          if (data?.errcode && data.errcode !== 0) {
            failure++
            errors.push({ openid, errcode: data.errcode, errmsg: data.errmsg })
          } else {
            success++
          }
        } catch (err) {
          failure++
          const body = err?.response?.data || {}
          errors.push({ openid, err: body?.errmsg || err.message })
        }
      })
    )
    // 简单延时，避免触发平台限流
    await new Promise((resolve) => setTimeout(resolve, delayMs))
  }
  return { total: openids.length, success, failure, errors }
}

// POST /api/weixin/sendTemplateMessageAll - 留空 openid 时发送给全部关注者
router.post('/sendTemplateMessageAll', async (req, res) => {
  try {
    const { template_id, data: tmplData, url, miniprogram, client_msg_id } = req.body || {}
    const missing = []
    if (!template_id) missing.push('模板 ID')
    const isDataEmpty = !tmplData || (typeof tmplData === 'object' && Object.keys(tmplData).length === 0)
    if (isDataEmpty) missing.push('模板数据')
    if (missing.length) {
      return res.status(400).json({ message: '必填参数不能为空：' + missing.join('、') })
    }
    const tokenInfo = await getAccessToken()
    const openids = await getAllOpenIds(tokenInfo.access_token)
    if (!openids.length) {
      return res.status(400).json({ message: '当前公众号无关注者或未授权获取用户列表' })
    }
    const basePayload = { data: tmplData, url, miniprogram, client_msg_id }
    const result = await sendTemplateToMany(tokenInfo.access_token, template_id, basePayload, openids)
    // 错误列表可能很长，仅返回前 20 条以避免响应过大
    const briefErrors = result.errors.slice(0, 20)
    return res.json({ total: result.total, success: result.success, failure: result.failure, errors: briefErrors })
  } catch (err) {
    const message = err?.response?.data || { message: err.message || '群发模板消息失败' }
    return res.status(400).json(message)
  }
})

module.exports = router